
// #include "unpifi.h"
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <inttypes.h>
#include <netinet/in.h>


void get_interface_list();

const char * sock_ntop(struct sockaddr_in * sai, socklen_t len) {

    // struct sockaddr_in * sai = (struct sockaddr_in*)sa;
    static char buffer[32];
    bzero(buffer, 32);
    inet_ntop(AF_INET, &sai->sin_addr, buffer, 32);
    
    return buffer;
}

const char * sock_ntop_help(struct sockaddr * sa, socklen_t len) {

    struct sockaddr_in * sai = (struct sockaddr_in*)sa;
    return sock_ntop(sai, len);
}

// compile code
int main(int argc, char * argv[]) {

    get_interface_list();
    // book code
    // struct ifi_info * ifi, * ifihead;
    // struct sockaddr * sa;

    // u_char * ptr;
    // int     i, family,  doaliases;

    // if (argc != 3) {

    //     printf("usgae: prififo <inet4 | inet6> <doaliaese>\n");
    //     return EXIT_FAILURE;
    // }
    // if (strcmp(argv[1], "inet4") == 0) {

    //     family = AF_INET;
    // } else if (strcmp(argv[1], "inet6") == 0) {

    //     family = AF_INET6;
    // } else {

    //     printf("invalid <address-famliy>");
    //     return EXIT_FAILURE;
    // }
    // doaliases = atoi(argv[2]);

    // for (ifihead = ifi = get_ifi_info(family, doaliases); ifi != NULL; ifi = ifi->ifi_next) {

    //     printf("%s: ", ifi->ifi_name);
    //     if (ifi->ifi_next != 0) {

    //         printf("(%d) ", ifi->ifi_index);
    //     }
    //     printf("<");
    //     if (ifi->ifi_flags & IFF_UP) {

    //         printf("UP ");
    //     }

    //     if (ifi->ifi_flags & IFF_BROADCAST) {

    //         printf("BCAST ");
    //     }

    //     if (ifi->ifi_flags & IFF_MULTICAST) {

    //         printf("MCAST ");
    //     }

    //     if (ifi->ifi_flags & IFF_LOOPBACK) {

    //         printf("LOOP ");
    //     }

    //     if (ifi->ifi_flags & IFF_POINTOPOINT) {

    //         printf("P2P ");
    //     }

    //     printf(">\n");
    //     if((i = ifi->ifi_hlen) > 0) {

    //         ptr = ifi->ifi_addr;
    //         do {

    //             printf("%s%x", (i == ifi->ifi_hlen) ? "  " : ":", *ptr++);

    //         }while(--i > 0);
    //         printf("\n");
    //     }
    //     if (ifi->ifi_mtu != 0) {

    //         printf(" MTU: %d\n", ifi->ifi_mtu);
    //     }

    //     if ((sa = ifi->ifi_addr) != NULL) {

    //         // printf("    IP addr: %s\n", )
    //     }
    //     if ((sa = ifi->ifi_brdaddr) != NULL) {

    //     }

    //     if ((sa = ifi->ifi_dstaddr) != NULL) {


    //     }
    // }
    // free_ifi_info(ifihead);
    return EXIT_SUCCESS;
}

#include <sys/ioctl.h>

// 接口 
// SIOCGIFCONF  -system ioc get ifconfig
void get_interface_list() {

    struct ifconf ifconfig;
    bzero(&ifconfig, sizeof(ifconfig));

    // malloc memory 
    char * buffer = malloc(1024 * sizeof(char));
    ifconfig.ifc_ifcu.ifcu_buf = buffer;
    ifconfig.ifc_len           = 1024;
    // TCP protocol
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {

        printf("create socket fd failure");
        return;
    }
    int result = ioctl(sockfd, SIOCGIFCONF, &ifconfig);
    if (result != 0) {

        printf("call ioctl function failure.\n");
        return;
    }
    struct ifreq * ifconfigPtr = (struct ifreq *)buffer;
    struct ifreq * backPtr = (struct ifreq *)buffer;
    
    int totalSize = ifconfig.ifc_len;
    totalSize = totalSize / sizeof(struct ifreq);
    for (int index = 1; index <= totalSize; index++) {

        struct ifreq * ifreqPtr = ifconfigPtr;
        printf("interface name : %s\n", ifreqPtr->ifr_ifrn.ifrn_name);
        struct sockaddr_in * sinptr = (struct sockaddr_in * )&ifreqPtr->ifr_ifru.ifru_addr;
        printf("interface name : %s\n", sock_ntop(sinptr, sizeof(struct sockaddr_in)));
        // test ioctl flag
        struct ifreq flags = *ifreqPtr;
        result = ioctl(sockfd, SIOCGIFFLAGS, &flags);
        if (result != 0) {

            // failure
        } else {

            if (flags.ifr_ifru.ifru_flags & IFF_UP) {

                printf("iff up status\n");
            }

            if (flags.ifr_ifru.ifru_flags & IFF_LOOPBACK) {

                printf("iff loopback status\n");
            }

            if (flags.ifr_ifru.ifru_flags & IFF_POINTOPOINT) {

                printf("p2p status\n");
            }

            if (flags.ifr_ifru.ifru_flags & IFF_RUNNING) {

                printf("%s interface is running\n", backPtr->ifr_ifrn.ifrn_name);
            }

            if(flags.ifr_ifru.ifru_flags & IFF_BROADCAST) {

                printf("broadcast address is valid\n");
            }

            if(flags.ifr_ifru.ifru_flags & IFF_MULTICAST) {

                printf("multi cast is valid\n");
            }
        }
        ifconfigPtr += index;
        printf("------------------------------------------\n");
    }
    free(buffer);
}

